package com.aplink.generic.webservice;

import java.io.File;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.json.JSONException;
import org.json.JSONObject;

import android.net.Uri;
import android.os.Build;
import android.text.TextUtils;

import com.aplink.generic.constant.WebServiceContant;
import com.aplink.generic.constant.type.ActionType;
import com.aplink.generic.network.GenericFile;
import com.aplink.generic.pojo.ContentData;
import com.aplink.generic.pojo.GenericObject;
import com.aplink.generic.pojo.ObjPropInfo;
import com.aplink.generic.sharepreference.GenericSharePreference;
import com.aplink.generic.util.LogUtil;

public class HttpURL {
	private static final String ACTION = "action";
	private static final String ALLOW_CHARACTER_URL = "@#&=*+-_.,:!?()/~'%";
	private static final String JSON_ACTION = "jsonAction";
	private static final String JSON_CONDITION = "jsonCondition";
	private static final String JSON_EMAIL = "email";
	private static final String JSON_TABLE = "table";
	private static final String JSON_TOKEN = "token";
	private static final String JSON_VALUE = "jsonValue";
	private boolean hasDownloadFile;
	private ActionType mActionType;
	private String mDomain;
	private String mEmail;
	private ObjPropInfo mFileObjPropInfo;
	private GenericObject mGenericEmail;
	private GenericObject mGenericObject;
	private String mJsonAction;
	private String mJsonCondition;
	private String mJsonValue;
	private ArrayList<GenericFile> mListDeleteFiles;
	private ArrayList<GenericFile> mListUploadFiles;
	private int mMethod = WebServiceContant.GET;
	private ContentData mObjPropCol;
	private String mTable;
	private String mToken;
	private String mWebserviceFunction;

	public HttpURL() {
		this.mListUploadFiles = new ArrayList<GenericFile>();
		this.mListDeleteFiles = new ArrayList<GenericFile>();
		this.mToken = GenericSharePreference.getInstance().getToken();
	}

	public HttpURL(final String jsonValue, final String jsonCondition,
	        final String action, final String table, final String domain,
	        final String webserviceFunction,
	        final ArrayList<GenericFile> listFiles) {
		this.mToken = GenericSharePreference.getInstance().getToken();
		this.mJsonValue = jsonValue;
		this.mJsonCondition = jsonCondition;
		this.mJsonAction = action;
		this.mTable = table;
		this.mDomain = domain;
		this.mWebserviceFunction = webserviceFunction;
		setListUploadFiles(listFiles);
		this.mListUploadFiles = new ArrayList<GenericFile>();
		this.mListDeleteFiles = new ArrayList<GenericFile>();
	}

	public String getAction() {
		return this.mJsonAction;
	}

	public ActionType getActionType() {
		return mActionType;
	}

	public ContentData getContentData() {
		return this.mObjPropCol;
	}

	public String getDomain() {
		return this.mDomain;
	}

	public ObjPropInfo getFileObjPropInfo() {
		return this.mFileObjPropInfo;
	}

	public GenericObject getGenericObject() {
		return this.mGenericObject;
	}

	private String getHttpGetData() {
		final StringBuilder url = new StringBuilder();
		url.append(this.mDomain).append(this.mWebserviceFunction);
		if (this.mMethod == WebServiceContant.GET) {
			try {
				// Append json action.
				JSONObject jsonObject = new JSONObject();
				if (this.mJsonAction == null) {
					url.append(String.format("%s={}", HttpURL.JSON_ACTION))
					        .append("&");
				} else {
					jsonObject.put(HttpURL.ACTION, this.mJsonAction);
					url.append(
					        String.format("%s=%s", HttpURL.JSON_ACTION,
					                jsonObject.toString())).append("&");
				}
				// Append json table.
				jsonObject = new JSONObject();
				if (this.mTable == null) {
					url.append(String.format("%s={}", HttpURL.JSON_TABLE))
					        .append("&");
				} else {
					jsonObject.put(HttpURL.JSON_TABLE, this.mTable);
					url.append(
					        String.format("%s=%s", HttpURL.JSON_TABLE,
					                jsonObject.toString())).append("&");
				}
				// Append json condition.
				jsonObject = new JSONObject();
				if (this.mJsonCondition == null) {
					url.append(String.format("%s={}", HttpURL.JSON_CONDITION))
					        .append("&");
				} else {
					jsonObject.put("CreatedTime", this.mJsonCondition);
					url.append(
					        String.format("%s=%s", HttpURL.JSON_CONDITION,
					                jsonObject.toString())).append("&");
				}

				// Append json token.
				jsonObject = new JSONObject();
				if (this.mToken == null) {
					url.append(String.format("%s={}", HttpURL.JSON_TOKEN))
					        .append("&");
				} else {
					jsonObject.put(HttpURL.JSON_TOKEN, this.mToken);
					url.append(
					        String.format("%s=%s", HttpURL.JSON_TOKEN,
					                jsonObject.toString())).append("&");
				}

				// Append json value.
				this.mJsonValue = parseJsonValue(this.mObjPropCol,
				        this.mGenericObject);
				if (this.mJsonValue == null) {
					url.append(String.format("%s={}", HttpURL.JSON_VALUE))
					        .append("&");
				} else {
					url.append(
					        String.format("%s=%s", HttpURL.JSON_VALUE,
					                this.mJsonValue)).append("&");
				}

				this.mEmail = parseJsonValue(this.mObjPropCol,
				        this.mGenericEmail);
				if (this.mEmail == null) {
					url.append(String.format("%s={}", HttpURL.JSON_EMAIL));
				} else {
					url.append(String.format("%s=%s", HttpURL.JSON_EMAIL,
					        this.mEmail));
				}
				return url.toString();
			} catch (final JSONException e) {
				e.printStackTrace();
			}
		}
		// }
		return url.toString();
	}

	public HttpEntity getHttpPostData() {
		if (this.mMethod == WebServiceContant.POST) {
			this.mJsonValue = parseJsonValue(this.mObjPropCol,
			        this.mGenericObject);
			final MultipartEntityBuilder builder = MultipartEntityBuilder
			        .create()
			        .addPart("token",
			                new StringBody(this.mToken, ContentType.TEXT_PLAIN))
			        .addPart(
			                "action",
			                new StringBody(this.mJsonAction,
			                        ContentType.TEXT_PLAIN))
			        .addPart(
			                "jsonValue",
			                new StringBody(this.mJsonValue,
			                        ContentType.TEXT_PLAIN))
			        .addPart("table",
			                new StringBody(this.mTable, ContentType.TEXT_PLAIN));
			if (this.mJsonCondition != null) {
				try {
					final JSONObject jsonObject = new JSONObject();
					jsonObject.put("CreatedTime", this.mJsonCondition);
					builder.addPart("jsonCondition",
					        new StringBody(jsonObject.toString(),
					                ContentType.TEXT_PLAIN));
				} catch (final JSONException e) {
					e.printStackTrace();
				}
			} else {
				builder.addPart("jsonCondition", new StringBody("{}",
				        ContentType.TEXT_PLAIN));
			}
			if (!this.mListUploadFiles.isEmpty()) {
				for (final GenericFile fileUrl : this.mListUploadFiles) {
					builder.addPart("image",
					        new FileBody(new File(fileUrl.getLocalPath())));
				}
			}

			final StringBuilder listDelete = new StringBuilder();
			for (int i = 0; i < this.mListDeleteFiles.size(); i++) {
				final GenericFile genericFile = this.mListDeleteFiles.get(i);
				final String fileName = genericFile.getName();
				listDelete.append(fileName);
				if (i < (this.mListDeleteFiles.size() - 1)) {
					listDelete.append(",");
				}
			}
			if (this.mJsonAction.equalsIgnoreCase("update")) {
				builder.addPart("imageDeleteList",
				        new StringBody(listDelete.toString(),
				                ContentType.TEXT_PLAIN));
			}
			return builder.build();
		}
		return null;
	}

	public String getJsonCondition() {
		return this.mJsonCondition;
	}

	public String getJsonValue() {
		return this.mJsonValue;
	}

	public ArrayList<GenericFile> getListDeleteFiles() {
		return this.mListDeleteFiles;
	}

	public ArrayList<GenericFile> getListFiles() {
		return this.mListUploadFiles;
	}

	public int getMethod() {
		return this.mMethod;
	}

	public String getToken() {
		return this.mToken;
	}

	public String getWebserviceFunction() {
		return this.mWebserviceFunction;
	}

	public String getWebserviceURL() {
		if (this.mMethod == WebServiceContant.GET) {
			return Uri.encode(getHttpGetData(), HttpURL.ALLOW_CHARACTER_URL);
		}
		return getHttpGetData();
	}

	public String initTableName() {
		return this.mTable;
	}

	public boolean isHasDownloadFile() {
		return this.hasDownloadFile;
	}

	private String parseJsonValue(final ContentData contentData,
	        final GenericObject genericObject) {
		if ((contentData == null) || (genericObject == null)) {
			return null;
		}
		final StringBuilder jsonValue = new StringBuilder();
		try {
			final JSONObject finalResult = new JSONObject();
			for (int i = 0; i < contentData.getWebServiceParameters().size(); i++) {
				final int columnName = contentData.getWebServiceParameters()
				        .keyAt(i);
				final String webserviceParameter = contentData
				        .getWebServiceParameters().valueAt(i);
				if (genericObject.containsKey(columnName)) {
					String value = genericObject.get(columnName).getValue();
					if (TextUtils.isEmpty(value)) {
						final ObjPropInfo propInfo = contentData
						        .get(columnName);
						if ((propInfo != null) && propInfo.isFKey()) {
							value = genericObject.get(
							        propInfo.getForeignFullColumnName())
							        .getValue();
						} else if (propInfo.isDeviceID()) {
							value = GenericSharePreference.getInstance()
							        .getRegistrationId();
							if (TextUtils.isEmpty(value)) {
								value = "no-device-token";
							}
						} else if (propInfo.isMobileOS()) {
							value = String.format(
							        "%s, Model:%s,Version:%s,SDK_INT:%s",
							        Build.MANUFACTURER, Build.MODEL,
							        Build.VERSION.RELEASE,
							        Build.VERSION.SDK_INT);
						}
						if (!TextUtils.isEmpty(value)) {
							finalResult.put(webserviceParameter, value);
						}
					} else {
						finalResult.put(webserviceParameter, value);
					}
				}
			}
			jsonValue.append(finalResult.toString());
		} catch (final JSONException e) {
			e.printStackTrace();
		}
		LogUtil.info("APLINK_JSON_VALUE", jsonValue.toString(),
		        "parseJsonValue", getClass());
		return jsonValue.toString();
	}

	public HttpURL setAction(final String action) {
		this.mJsonAction = action;
		return this;
	}

	public void setActionType(ActionType actionType) {
		mActionType = actionType;
	}

	public HttpURL setContentData(final ContentData objPropCol) {
		this.mObjPropCol = objPropCol;
		return this;
	}

	public HttpURL setDomain(final String domain) {
		this.mDomain = domain;
		return this;
	}

	public HttpURL setEmail(final GenericObject genericObject) {
		this.mGenericEmail = genericObject;
		return this;
	}

	public void setFileObjPropInfo(final ObjPropInfo fileObjPropInfo) {
		this.mFileObjPropInfo = fileObjPropInfo;
	}

	public void setGenericObject(final GenericObject genericObject) {
		this.mGenericObject = genericObject;
	}

	public void setHasDownloadFile(final boolean hasDownloadFile) {
		this.hasDownloadFile = hasDownloadFile;
	}

	public HttpURL setJsonCondition(final String jsonCondition) {
		this.mJsonCondition = jsonCondition;
		return this;
	}

	public HttpURL setJsonValue(final GenericObject genericObject) {
		this.mGenericObject = genericObject;
		return this;
	}

	public HttpURL setListDeleteFiles(
	        final ArrayList<GenericFile> listDeleteFiles) {
		this.mListDeleteFiles = listDeleteFiles;
		return this;
	}

	public HttpURL setListUploadFiles(final ArrayList<GenericFile> listFiles) {
		this.mListUploadFiles = listFiles;
		return this;
	}

	public HttpURL setMethod(final int method) {
		this.mMethod = method;
		return this;
	}

	public HttpURL setTable(final String table) {
		this.mTable = table;
		return this;
	}

	public HttpURL setToken(final String token) {
		this.mToken = token;
		return this;
	}

	public HttpURL setWebserviceFunction(final String webserviceFunction) {
		this.mWebserviceFunction = webserviceFunction;
		return this;
	}

	@Override
	public String toString() {
		return getHttpGetData();
	}
}
